// package rdf defines the core interfaces used for
// manipulating RDF and some simple implementations
// of those interfaces.
package rdf

import "strconv"
import "trigger.googlecode.com/hg/lib/uri"

// RDF is the RDF namespace URI.
const RDF = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"

// FIRST is a URI Node representing rdf:first.
const FIRST = URIString( RDF + "first" )

// REST is a URI Node representing rdf:rest.
const REST = URIString( RDF + "rest" )

// NIL is a URI Node representing rdf:nil.
const NIL = URIString( RDF + "nil" )

// A Dataset is a collection of named graphs and a default
// graph.
type Dataset interface {
    GraphNamed(name string) Graph
    DefaultGraph() Graph
}

// A Graph stores a set of Triples, and allows triples
// to be added, removed, and inspected.
type Graph interface {
    // Add(t) adds t to the set of triples. It returns
    // true iff the triple was not already present.
    Add(t Triple) bool

    // Remove(t) removes t from the set of triples. It
    // returns true iff the triple was previously present.
    Remove(t Triple) bool

    // Contains(t) returns true iff t is present in the set.
    Contains(t Triple) bool

    // FindAll(t, f) applies f to each triple in the set
    // that matches t. If f returns false, the scan of
    // matching triples is terminated early. FindAll returns
    // true if all the matching triples were passed to f
    // and false if f ever returns false.
    FindAll(t Triple, f func(Triple)bool ) bool
}

// A Triple holds Subject, Predicate, and Object Nodes.
type Triple interface {
    // t.S() returns the subject of the triple.
    S() Node
    // t.P() returns the predicate of the triple
    P() Node
    // t.O() returns the object of the triple
    O() Node
    // t.SPO() returns (t.S(), t.P(), t.O())
    SPO() (Node, Node, Node)
    // The flags of a triple are the union of the
    // flags of its nodes and also the field-shifted
    // flags.
    Is() Flags
}

type triple struct {s, p, o Node}

func (t *triple) S() Node { return t.s}

func (t *triple) P() Node { return t.p}

func (t *triple) O() Node { return t.o}

func (t *triple) SPO() (Node, Node, Node) { return t.s, t.p, t.o }

func (t *triple) Is() Flags {
    sf, pf, of := t.s.Is(), t.p.Is(), t.o.Is()
    return (sf << SHIFT_S) | (pf << SHIFT_P) | (of << SHIFT_O) | sf | pf | of
}

func AsTriple(S, P, O Node) Triple {
    return &triple{S, P, O}
}

// Flags specify information about Nodes and Triples.
type Flags uint32

const (
    IS_URI Flags = 1 << iota
    IS_LITERAL
    IS_BNODE
    IS_VARIABLE
    IS_SYMBOL
    HAS_DATATYPE
    HAS_LANGUAGE
)

const (
    SHIFT_S = 8
    SHIFT_P = 16
    SHIFT_O = 24
)

// A Node may be a Literal, BNode, Resource, Variable, or Symbol.
// (Thanks to Andy for that latter suggestion.) Which it is may
// be distinguished by its Flags and/or type tests.
type Node interface {
    // Is() returns the node flags of this node.
    Is() Flags
    // Value() returns an equality value for this node 
    Value() interface{}
}

// A Literal object has a lexical form (mandatory), a language
// code, and a datatype URI (optional, not both).
type Literal interface {
    Node
    LexicalForm() string
    Language() string
    DataType() string
}

// A BNode has an internal anonymous Id.
type BNode interface {
    Node
    AnonId() string
}

// A Resource (bad name) is a URI Node.
type Resource interface {
    Node
    URI() uri.Type
}

// A Variable is a placeholder or bindable object in a query.
type Variable interface {
    Node
    Name() string
}

// A Symbol is a non-RDF marker Node.
type Symbol interface {
    Node
    SymString() string
}

// A literal is a syntactic implementation of Literal.
type literal struct {
    lexicalForm, language, dataType string
}

func AsLiteral(lexicalForm, language, dataType string) *literal {
    return &literal{lexicalForm, language, dataType}
}

func (l *literal) Is() Flags {
    result := IS_LITERAL
    if l.language != "" { result |= HAS_LANGUAGE }
    if l.dataType != "" { result |= HAS_DATATYPE }
    return result
}

func (l *literal) Value() interface{} {
    return l.language + "--" + l.dataType + "--" + l.lexicalForm
}

func (l *literal) LexicalForm() string {
    return l.lexicalForm
}

func (l *literal) Language() string {
    return l.language
}

func (l *literal) DataType() string {
    return l.dataType
}

// A URIString is a syntactic implementation of Resource.
type URIString string

func AsURI(u string) Resource {
    return URIString(u)
}

func (u URIString) Is() Flags {
    return IS_URI
}

func (u URIString) URI() uri.Type {
    return uri.Type(string(u))
}

func (u URIString) Value() interface{} {
    return string(u)
}

var bcount = 1000

type bnode int

func NewBNode() Node {
    bcount += 1
    return bnode(bcount)
}

func (b bnode) AnonId() string {
    return "_:" + strconv.Itoa(int(b))
}

func (b bnode) Value() interface {} {
    return b
}

func (b bnode) Is() Flags {
    return IS_BNODE
}
